package com.atguigu.lease.app.service.impl;

import com.alibaba.fastjson2.JSON;
import com.atguigu.lease.app.service.UserInfoService;
import com.atguigu.lease.app.service.UserLoginService;
import com.atguigu.lease.common.util.HttpUtils;
import com.atguigu.lease.common.util.JwtUtil;
import com.atguigu.lease.common.util.ValidateUtil;
import com.atguigu.lease.model.bean.UserInfo;
import com.atguigu.lease.model.dto.app.LoginSubmitDto;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.RandomUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class UserLoginServiceImpl implements UserLoginService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Override
    public void getCode(String phone) {
        //1、校验手机号格式: 正则表达式校验
        ValidateUtil.phoneValidate(phone);
        //2、校验手机号获取验证码的频率：
        // 表单重复提交 :一分钟内 只能获取一次验证码: setnx 当键不存在时才设置
        //   stgy:login:interval:1351111111
        String intervalKey = "stgy:login:interval:"+phone;
        if(!stringRedisTemplate.opsForValue()
                .setIfAbsent(intervalKey , "1" , 1 , TimeUnit.MINUTES)){
            // key设置失败，表示1分钟内 这个手机号已经获取过验证码，不能重复获取
            throw new RuntimeException("重复获取验证码!");
        }
        // 刷短信: 一天内 只能获取5次验证码
        String countKey = "stgy:login:count:" + phone;
        String count = stringRedisTemplate.opsForValue().get(countKey);
        if(!StringUtils.isEmpty(count) &&  Long.parseLong(count) >= 5 ){
            throw new RuntimeException("获取验证码异常");
        }
        //3、生成验证码、调用第三方的接口给手机号发送短信
        String code = RandomUtils.nextInt(100000, 999999)+"";
        //调用第三方接口 发送验证码的业务方法
        System.out.println("code:"+code );
//        sendMsg(phone , code);
        //4、短信发送成功：
        // 缓存验证码到redis中(过期时间10分钟)
        String key = "stgy:login:code:" + phone;
        stringRedisTemplate.opsForValue().set(key,code , 10, TimeUnit.MINUTES);
        //        更新手机号获取验证码的频率次数
        // 一天内 手机号获取验证码的次数
        if(stringRedisTemplate.opsForValue().increment(countKey).longValue() == 1l){
            // countKey 第一次自增，为这个键设置过期时间
            stringRedisTemplate.expire(countKey, 1, TimeUnit.DAYS);
        }


    }

    private void sendMsg(String phone,String code){
        // 第三方短信平台的服务器地址
        String host = "https://cxkjsms.market.alicloudapi.com";
        // 短信接口 资源路径
        String path = "/chuangxinsms/dxjk";
        // 请求方式
        String method = "POST";
        // 我们购买 第三方平台 短信资源的 code码
        String appcode = "8e45699f00ff4bdbb807664045acd813";//开通服务后 买家中心-查看AppCode
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        // 请求参数map
        Map<String, String> querys = new HashMap<String, String>();
        //   短信模板： 只能修改验证码
        querys.put("content", "【创信】你的验证码是："+code+"，3分钟内有效！");
        //   手机号
        querys.put("mobile", phone);
        Map<String, String> bodys = new HashMap<String, String>();


        try {
            // 发送请求 并接收响应结果
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
//            System.out.println(response.toString());
            //获取response的body： 获取响应体内容
            String body = EntityUtils.toString(response.getEntity());
            //解析json字符串： 判断短信发送成功还是失败
            Map map = JSON.parseObject(body, Map.class);
            /**
             * {
             *   "ReturnStatus": "Success",
             *   "Message": "ok",
             *   "RemainPoint": 420842,
             *   "TaskID": 18424321,
             *   "SuccessCounts": 1
             * }
             */
            Object returnStatus = map.get("ReturnStatus");
            if(returnStatus!=null && "Success".equalsIgnoreCase(returnStatus.toString())){
                //验证码发送成功
                System.out.println("短信发送成功");
            }else{
                System.out.println("短信发送失败");
                throw new RuntimeException("短信发送失败");
            }
            System.out.println("短信发送的结果："+ body);
            //System.out.println(EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("短信发送失败");
        }
    }

    @Autowired
    UserInfoService userInfoService;
    @Override
    public String login(LoginSubmitDto loginSubmitDto) {
        //1、校验手机号码格式是否正确
        String phone = loginSubmitDto.getPhone();
        ValidateUtil.phoneValidate(phone);
        //2、校验验证码是否正确： 和redis中缓存的比较
        String code = loginSubmitDto.getCode();//获取前端用户输入提交的验证码

        //获取redis中缓存的 这个手机号的验证码
        String key = "stgy:login:code:" + phone;
        String redisCachedCode = stringRedisTemplate.opsForValue().get(key);

        if(StringUtils.isEmpty(code) || !code.equalsIgnoreCase(redisCachedCode) ){
            //客户端提交的验证码错误
            throw new RuntimeException("验证码错误!");
        }
        //删除验证码: 防止表单重复提交
        stringRedisTemplate.delete(key);
        //3、通过手机号获取用户信息
        UserInfo userInfo = userInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class)
                .eq(UserInfo::getPhone, phone));
        if(userInfo == null){
            // 3.1 获取失败： 手机号第一次访问stgy，帮助用户完成注册
            userInfo = new UserInfo();
            userInfo.setNickname("我是一个小可爱_"+ UUID.randomUUID().toString().substring(0,8));
            userInfo.setPhone(phone);
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            userInfo.setStatus(1);//1 可用状态 0禁用
            userInfo.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
            userInfoService.save(userInfo);
        }
        // 3.2 获取成功： 第N次访问
        //4、根据查询到的用户 或者 新创建的用户 信息创建jwt返回
        return JwtUtil.createJwt(userInfo.getId() , userInfo.getNickname(),
                userInfo.getAvatarUrl());
    }


}
